package com.PTA.KeSheView;

import com.PTA.KeShe.Block;
import com.PTA.KeShe.HandleImage;
import com.PTA.KeShe.Point;
import com.PTA.KeShe.VerifySuccess;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Collectors;

//PuzzlePad类是javax.swing包中JPanel容器的子类，其实例就是魔板。该类使用二维数组Point来确定魔板中方块的位置，使用二维数组Block作为魔板中的方块。
// distance、grade、m和n是int型数据，Point对象根据distance的值进行初始化，以便确定Point对象之间的距离。
// m和n是Point对象数组的行和列，m和n的默认值都是3。grade的值代表魔板的级别。默认值是1。
// PUzzle Pad对象调用setIsDigitPlay（）方法将魔板设置为数字玩法，调用paintComponent(Graphics)方法将魔板使用的图像绘制在魔板的右侧，调用move()方法将魔板移动。
// 拼图板类，继承自 JPanel
public class PuzzlePad extends JPanel {
    Point[][] point;    // 魔板中的全部点，表示方块的坐标位置
    Block[][] block;    // 魔板中的全部方块
    int distance = 56;  // 方块之间的间距
    int grade;          // 当前难度级别
    int m = 3;          // 行数
    int n = 3;          // 列数
    HandleMove handleMove; // 处理方块移动的类
    HandleImage handleImage; // 处理图像分割的类
    VerifySuccess verifySuccess; // 验证拼图是否成功的类
    Image image;        // 当前使用的拼图图像
    boolean isDigitPlay; // 标识当前是数字玩法还是图像玩法

    // 构造方法，初始化拼图板
    public PuzzlePad() {
        setBackground(Color.gray); // 设置背景颜色
        setLayout(null); // 使用空布局
        handleMove = new HandleMove(); // 初始化处理移动的类
        handleMove.initSpendTime(); // 初始化计时器
        handleImage = new HandleImage(); // 初始化处理图像的类
        verifySuccess = new VerifySuccess(); // 初始化验证拼图成功的类
        handleMove.setVerifySuccess(verifySuccess); // 设置验证类给移动处理类
    }

    // 获取移动处理类
    public HandleMove getHandleMove() {
        return handleMove;
    }

    // 设置拼图的图像
    public void setImage(Image image) {
        this.image = image;
    }

    // 设置拼图的难度级别
    public void setGrade(int grade) {
        this.grade = grade;
        if (grade == 1) {
            m = 3; // 初级为 3x3
            n = 3;
        } else if (grade == 2) {
            m = 4; // 高级为 4x4
            n = 4;
        }
    }

    // 获取当前难度级别
    public int getGrade() {
        return grade;
    }

    // 初始化拼图所需的数据和布局
    private void needInit() {
        handleMove.initSpendTime(); // 初始化计时器
        removeAll(); // 移除所有组件

        // 初始化点数组和方块数组
        point = new Point[m][n];
        block = new Block[m][n];

        int Hspace = distance, Vspace = distance;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                point[i][j] = new Point(Hspace, Vspace); // 初始化每个点的位置
                Hspace += distance; // 更新水平间距
            }
            Hspace = distance; // 重置水平间距
            Vspace += distance; // 更新垂直间距
        }

        // 设置点数组到移动处理类和验证类
        handleMove.setPoint(point);
        verifySuccess.setPoint(point);
        handleMove.setVerifySuccess(verifySuccess);

        // 初始化方块
        int k = 0;
        for (int i = 0; i < m; i++) {
            if (i < m - 1) {
                for (int j = 0; j < n; j++) {
                    block[i][j] = new Block();
                    block[i][j].setAllPoint(point); // 设置方块可访问的点数组
                    block[i][j].addMouseListener(handleMove); // 添加鼠标监听器
                    k++;
                }
            } else {
                for (int j = 0; j < n - 1; j++) {
                    block[i][j] = new Block();
                    block[i][j].setAllPoint(point);
                    block[i][j].addMouseListener(handleMove);
                    k++;
                }
            }
        }

        // 将方块添加到面板中
        for (int i = 0; i < m; i++) {
            if (i < m - 1) {
                for (int j = 0; j < n; j++) {
                    add(block[i][j]);
                    block[i][j].setSize(distance, distance); // 设置方块大小
                    block[i][j].setLocation(point[i][j].getX(), point[i][j].getY()); // 设置方块位置
                    block[i][j].setAtPoint(point[i][j]); // 绑定方块到点
                    point[i][j].setBlock(block[i][j]); // 绑定点到方块
                    point[i][j].setHaveBlock(true); // 标记点上有方块
                }
            } else {
                for (int j = 0; j < n - 1; j++) {
                    add(block[i][j]);
                    block[i][j].setSize(distance, distance);
                    block[i][j].setLocation(point[i][j].getX(), point[i][j].getY());
                    block[i][j].setAtPoint(point[i][j]);
                    point[i][j].setBlock(block[i][j]);
                    point[i][j].setHaveBlock(true);
                }
            }
        }
    }

    // 初始化数字玩法
    public void setIsDigitPlay() {
        needInit(); // 初始化拼图板
        isDigitPlay = true;
        ArrayList<Integer> numberList = new ArrayList<>();
        for (int k = 0; k < m * n - 1; k++) {
            numberList.add(k + 1); // 生成数字序列
        }
        Object[] object = numberList.toArray();
        verifySuccess.setObject(object); // 设置验证对象
        Collections.shuffle(numberList); // 随机打乱数字序列

        int k = 0;
        for (int i = 0; i < m; i++) {
            if (i < m - 1) {
                for (int j = 0; j < n; j++) {
                    block[i][j].setObject(numberList.get(k)); // 设置方块内容为数字
                    k++;
                }
            } else {
                for (int j = 0; j < n - 1; j++) {
                    block[i][j].setObject(numberList.get(k));
                    k++;
                }
            }
        }
        repaint(); // 重绘面板
    }

    // 初始化图像玩法
    public void setIsImagePlay() {
        needInit(); // 初始化拼图板
        isDigitPlay = false;
        ArrayList<Image> imageList = new ArrayList<>();
        Image[] blockImage = handleImage.getImages(image, m, n); // 获取分割后的图像
        for (int k = 0; k < blockImage.length; k++) {
            imageList.add(blockImage[k]);
        }
        Object[] object = imageList.toArray();
        verifySuccess.setObject(object); // 设置验证对象
        Collections.shuffle(imageList); // 随机打乱图像顺序

        int k = 0;
        for (int i = 0; i < m; i++) {
            if (i < m - 1) {
                for (int j = 0; j < n; j++) {
                    block[i][j].setObject(imageList.get(k)); // 设置方块内容为图像
                    block[i][j].repaint(); // 重绘方块
                    block[i][j].setBorder(null); // 移除边框
                    k++;
                }
            } else {
                for (int j = 0; j < n - 1; j++) {
                    block[i][j].setObject(imageList.get(k));
                    block[i][j].repaint();
                    block[i][j].setBorder(null);
                    k++;
                }
            }
        }
        repaint(); // 重绘面板
    }

    // 绘制拼图面板
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (!isDigitPlay) { // 如果是图像玩法
            try {
                g.drawImage(image, 20 + distance * (m + 1), point[0][0].getY(), distance * m, distance * n, this); // 绘制完整图像
            } catch (Exception exp) {
                exp.printStackTrace();
            }
        }
    }
}
